package com.yang.Offer;

/*请实现一个函数用来判断字符串是否表示数值（包括整数和小数）。

数值（按顺序）可以分成以下几个部分：

    若干空格
    一个 小数 或者 整数
    （可选）一个 'e' 或 'E' ，后面跟着一个 整数
    若干空格

小数（按顺序）可以分成以下几个部分：

    （可选）一个符号字符（'+' 或 '-'）
    下述格式之一：
        至少一位数字，后面跟着一个点 '.'
        至少一位数字，后面跟着一个点 '.' ，后面再跟着至少一位数字
        一个点 '.' ，后面跟着至少一位数字

整数（按顺序）可以分成以下几个部分：

    （可选）一个符号字符（'+' 或 '-'）
    至少一位数字

部分数值列举如下：

    ["+100", "5e2", "-123", "3.1416", "-1E-16", "0123"]

部分非数值列举如下：

    ["12e", "1a3.14", "1.2.3", "+-5", "12e+5.4"]
*/
public class Offer20 {
}
class Offer20Solution {
    public boolean isNumber(String s) {
        // 整数部分不是必须的,但是没有整数就必须有小数部分
        // E或e后面必须跟着一个整数

        // 分析其实主要就是这几个状态
        // 1.数字
        // 2.正负号 正负号只能出现在最开始 或者 Ee的后面
        // 3.小数点 小数点只能出现一次 且且如果前面有e那么后面必须是整数(就是不能再出现小数)若是前面没有出现整数，那么小数部分必须要有整数
        // 4.E e E或e 前面与后面必须要有整数部分 且不能重复出现e E
        // 5.空格  空格只能出现在前面和后面，中间不能出现

        if (s.length() == 0 || s == null){
            return false;
        }
        // 定义是否遇到小数点 Ee 整数部分
        boolean numsFlag = false, decFlag = false, eFlag = false;
        // 去掉前后空格
        char[] string = s.trim().toCharArray();
        for(int i = 0; i < string.length; i++){
            if('0' <= string[i] && string[i] <= '9'){
                numsFlag = true;
            }else if(string[i] == '.'){
                // 小数点只能出现一次，且如果前面有e那么后面必须是整数
                if(decFlag || eFlag){
                    return false;
                }else{
                    decFlag = true;
                }
            }else if(string[i] == 'e' || string[i] == 'E'){
                // 如果 是e或E 那么它的前面必须有整数 且 Ee是第一次出现
                if(eFlag || !numsFlag){
                    return false;
                }else{
                    eFlag = true;
                    numsFlag = false;
                }
            }else if(string[i] == '-' || string[i] == '+'){
                // 如果是正负号，那么它要么出现在首位 要么就是它的前面有e 或 E
                if(i != 0 && string[i - 1] != 'e' && string[i - 1] != 'E'){
                    return false;
                }
            }else{
                return false;
            }
        }
        return numsFlag;
    }
}
